# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-05 23:30
# File     : project.py
# Project  : codebuddy_craft
# Desc     :
# backend/schemas/project.py
"""
项目数据模式定义 📁

定义项目相关的请求和响应数据结构
"""

from pydantic import BaseModel, Field, validator
from typing import Optional, List, Dict, Any
from datetime import datetime
from enum import Enum

from backend.models.project import ProjectStatus, ProjectVisibility, CollaboratorRole


class ProjectCreateRequest(BaseModel):
    """创建项目请求模型 ✨"""
    name: str = Field(..., min_length=1, max_length=100, description="项目名称")
    description: Optional[str] = Field(None, max_length=1000, description="项目描述")
    tech_stack: Optional[List[str]] = Field(default_factory=list, description="技术栈")
    visibility: Optional[ProjectVisibility] = Field(ProjectVisibility.PRIVATE, description="可见性")
    settings: Optional[Dict[str, Any]] = Field(default_factory=dict, description="项目设置")
    tags: Optional[List[str]] = Field(default_factory=list, description="标签")
    template_id: Optional[str] = Field(None, description="模板ID")

    @validator('name')
    def validate_name(cls, v):
        """验证项目名称"""
        if not v.strip():
            raise ValueError("项目名称不能为空")

        # 禁止的字符
        forbidden_chars = ['<', '>', ':', '"', '|', '?', '*', '\\', '/']
        for char in forbidden_chars:
            if char in v:
                raise ValueError(f"项目名称不能包含字符: {char}")

        return v.strip()

    @validator('tech_stack')
    def validate_tech_stack(cls, v):
        """验证技术栈"""
        if v and len(v) > 10:
            raise ValueError("技术栈不能超过10个")
        return v or []

    @validator('tags')
    def validate_tags(cls, v):
        """验证标签"""
        if v and len(v) > 20:
            raise ValueError("标签不能超过20个")
        return v or []


class ProjectUpdateRequest(BaseModel):
    """更新项目请求模型 ✏️"""
    name: Optional[str] = Field(None, min_length=1, max_length=100, description="项目名称")
    description: Optional[str] = Field(None, max_length=1000, description="项目描述")
    tech_stack: Optional[List[str]] = Field(None, description="技术栈")
    visibility: Optional[ProjectVisibility] = Field(None, description="可见性")
    settings: Optional[Dict[str, Any]] = Field(None, description="项目设置")
    tags: Optional[List[str]] = Field(None, description="标签")

    @validator('name')
    def validate_name(cls, v):
        """验证项目名称"""
        if v is not None:
            if not v.strip():
                raise ValueError("项目名称不能为空")

            # 禁止的字符
            forbidden_chars = ['<', '>', ':', '"', '|', '?', '*', '\\', '/']
            for char in forbidden_chars:
                if char in v:
                    raise ValueError(f"项目名称不能包含字符: {char}")

            return v.strip()
        return v


class ProjectResponse(BaseModel):
    """项目响应模型 📖"""
    id: str = Field(..., description="项目ID")
    name: str = Field(..., description="项目名称")
    description: Optional[str] = Field(None, description="项目描述")
    tech_stack: List[str] = Field(default_factory=list, description="技术栈")
    status: ProjectStatus = Field(..., description="项目状态")
    visibility: ProjectVisibility = Field(..., description="可见性")
    settings: Dict[str, Any] = Field(default_factory=dict, description="项目设置")
    tags: List[str] = Field(default_factory=list, description="标签")
    file_count: int = Field(..., description="文件数量")
    total_lines: int = Field(..., description="总代码行数")
    owner_id: str = Field(..., description="所有者ID")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    last_accessed_at: Optional[datetime] = Field(None, description="最后访问时间")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }


class ProjectListResponse(BaseModel):
    """项目列表响应模型 📋"""
    items: List[ProjectResponse] = Field(..., description="项目列表")
    total: int = Field(..., description="项目总数")
    skip: int = Field(..., description="跳过数量")
    limit: int = Field(..., description="返回数量")

    class Config:
        from_attributes = True


class CollaboratorAddRequest(BaseModel):
    """添加协作者请求模型 ➕"""
    username_or_email: str = Field(..., description="用户名或邮箱")
    role: CollaboratorRole = Field(..., description="协作者角色")
    permissions: Optional[Dict[str, Any]] = Field(default_factory=dict, description="权限设置")

    @validator('username_or_email')
    def validate_username_or_email(cls, v):
        """验证用户名或邮箱"""
        return v.strip().lower()


class CollaboratorResponse(BaseModel):
    """协作者响应模型 👥"""
    id: str = Field(..., description="协作者记录ID")
    user_id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    full_name: Optional[str] = Field(None, description="全名")
    avatar_url: Optional[str] = Field(None, description="头像URL")
    role: CollaboratorRole = Field(..., description="协作者角色")
    permissions: Dict[str, Any] = Field(default_factory=dict, description="权限设置")
    created_at: Optional[datetime] = Field(None, description="加入时间")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }

    @classmethod
    def from_orm(cls, obj):
        """从ORM对象创建响应模型"""
        return cls(
            id=obj.id,
            user_id=obj.user_id,
            username=obj.user.username,
            full_name=obj.user.full_name,
            avatar_url=obj.user.avatar_url,
            role=obj.role,
            permissions=obj.permissions or {},
            created_at=obj.created_at
        )


class ProjectTemplateResponse(BaseModel):
    """项目模板响应模型 📋"""
    id: str = Field(..., description="模板ID")
    name: str = Field(..., description="模板名称")
    description: Optional[str] = Field(None, description="模板描述")
    tech_stack: List[str] = Field(default_factory=list, description="技术栈")
    category: Optional[str] = Field(None, description="分类")
    tags: List[str] = Field(default_factory=list, description="标签")
    usage_count: int = Field(..., description="使用次数")
    is_public: bool = Field(..., description="是否公开")
    created_by: Optional[str] = Field(None, description="创建者ID")
    created_at: Optional[datetime] = Field(None, description="创建时间")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }
